<script setup lang="ts">
import { computed, nextTick, ref, useTemplateRef, watch } from "vue";
import { useRouter } from "vue-router";
import { useUser } from "@/stores/useUser";
import {
	onSocketInited,
	socketAddDelayedCards,
	socketAddMaterielCards,
	socketGetDiscardCards,
	socketGetDrawCards,
	socketGetPlayerCards,
	socketGetRoomState,
	socketJoinRoom,
	socketSetDead,
	socketLeaveRoom,
	socketSetFlipped,
	socketSetHealth,
	socketSetHealthLimit,
	socketSetHeros,
	socketSetHiddenHeros,
	socketSetTied,
	socketShuffle,
	socketSpeak,
	socketStartGame,
	socketTransferDelayedCardsToPlayerDelayedCards,
	socketTransferDiscardCardsToDiscardCards,
	socketTransferDiscardCardsToDrawCards,
	socketTransferDrawCardsToDiscardCards,
	socketTransferDrawCardsToDrawCards,
	socketTransferPlayerCardsToDiscardCards,
	socketTransferPlayerCardsToDrawCards,
	socketTransferPlayerCardsToPlayerHandCards,
	socketViewDiscardCards,
	socketViewDrawCards,
	socketAddBuckleCards,
} from "@/services/socket";
import { onRoomInited, useRoomState } from "@/hooks/useRoomState";
import { STATIC_URL } from "@/configs/yz";
import type { Hero } from "@/types/Hero";
import type { Card } from "@/types/Card";
import Picker from "@/components/picker";
import HerosPicker from "./components/HerosPicker.vue";
import CardsPicker from "./components/CardsPicker.vue";
import suit_icon_dict from "@/assets/data/suit_icon_dict.json";
import PlayerCardsPicker from "./components/PlayerCardsPicker.vue";
import HeroDetail from "./components/HeroDetail.vue";
import CardDetail from "./components/CardDetail.vue";
import type { Skill } from "@/types/Skill";
import { deepClone } from "@/utils/conversion";

const router = useRouter();
const userStore = useUser();
const roomState = useRoomState();
const oLog = useTemplateRef("oLog");
const oHerosPicker = useTemplateRef("oHerosPicker");
const oCardsPicker = useTemplateRef("oCardsPicker");
const oPlayerCardsPicker = useTemplateRef("oPlayerCardsPicker");
const oHeroDetail = useTemplateRef("oHeroDetail");
const oCardDetail = useTemplateRef("oCardDetail");
const logExpanded = ref(false);
const userPlayer = computed(() => roomState.room.value?.players.find((v) => v.user.userId === userStore.userInfo.userId) || null);
const otherPlayersV2 = computed(() => {
	const index = roomState.room.value?.players.findIndex((v) => v.user.userId === userStore.userInfo.userId);
	if (roomState.room.value && index !== void 0 && index !== -1) return roomState.room.value.players.slice(index + 1).concat(roomState.room.value.players.slice(0, index));
	else return [];
});
watch(
	() => roomState.room.value?.logs,
	() => nextTick(() => oLog.value?.children[oLog.value?.children.length - 1]?.scrollIntoView({ block: "end" })),
	{ deep: true }
);
init();
async function init() {
	await onSocketInited();
	socketGetRoomState();
	await onRoomInited();
	socketJoinRoom({ roomId: roomState.room.value!.roomId });
}
const openMenu = async () => {
	const value = await Picker([
		{ label: "开始游戏", value: "开始游戏" },
		{ label: "退出房间", value: "退出房间" },
		{ label: "洗牌", value: "洗牌" },
	]);
	switch (value) {
		case "开始游戏": {
			socketStartGame({ roomId: roomState.room.value!.roomId });
			break;
		}
		case "退出房间": {
			socketLeaveRoom({ roomId: roomState.room.value!.roomId });
			roomState.room.value = null;
			router.back();
			break;
		}
		case "洗牌": {
			socketShuffle({ roomId: roomState.room.value!.roomId });
			break;
		}
	}
};
const setUserPlayerHero = async () => {
	const value = await Picker([
		{ label: "选择武将", value: "选择武将" },
		{ label: "选择主公武将", value: "选择主公武将" },
		{ label: "设置武将暗置状态", value: "设置武将暗置状态" },
		{ label: "切换翻面状态", value: "切换翻面状态" },
		{ label: "切换铁索连环状态", value: "切换铁索连环状态" },
		{ label: "增加生命值", value: "增加生命值" },
		{ label: "减少生命值", value: "减少生命值" },
		{ label: "添加装备牌", value: "添加装备牌" },
		{ label: "添加延时牌", value: "添加延时牌" },
		{ label: "添加扣至牌", value: "添加扣至牌" },
		{ label: "获得牌", value: "获得牌" },
		{ label: "弃置牌", value: "弃置牌" },
		{ label: "延时牌置于下一人", value: "延时牌置于下一人" },
		{ label: "设置生命上限", value: "设置生命上限" },
		{ label: "重设已有武将", value: "重设已有武将" },
		{ label: "切换死亡状态", value: "切换死亡状态" },
	]);
	switch (value) {
		case "选择武将": {
			const ids = await oHerosPicker.value?.open({ heros: roomState.room.value!.heros, hidden: true, selectedIds: [] });
			if (ids) socketSetHeros({ roomId: roomState.room.value!.roomId, heroIds: ids });
			break;
		}
		case "选择主公武将": {
			socketSpeak({ roomId: roomState.room.value!.roomId, message: userStore.userInfo.username + "查看了主公武将。" });
			const ids = await oHerosPicker.value?.open({ heros: roomState.room.value!.heros, hidden: false, tetrarch: true, selectedIds: [] });
			if (ids) socketSetHeros({ roomId: roomState.room.value!.roomId, heroIds: ids });
			break;
		}
		case "设置武将暗置状态": {
			const ids = await oHerosPicker.value?.open({ heros: userPlayer.value!.heros, hidden: false, selectedIds: userPlayer.value!.hiddenHeroIds });
			if (ids) socketSetHiddenHeros({ roomId: roomState.room.value!.roomId, hiddenHeroIds: ids });
			break;
		}
		case "切换翻面状态": {
			socketSetFlipped({ roomId: roomState.room.value!.roomId, flipped: !userPlayer.value!.flipped });
			break;
		}
		case "切换铁索连环状态": {
			socketSetTied({ roomId: roomState.room.value!.roomId, tied: !userPlayer.value!.tied });
			break;
		}
		case "添加装备牌": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketAddMaterielCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId: userPlayer.value!.user.userId });
			break;
		}
		case "添加延时牌": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketAddDelayedCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId: userPlayer.value!.user.userId });
			break;
		}
		case "添加扣至牌": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketAddBuckleCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId: userPlayer.value!.user.userId });
			break;
		}
		case "获得牌": {
			const ids = await oPlayerCardsPicker.value?.open({
				buckleCards: userPlayer.value!.buckleCards,
				delayedCards: userPlayer.value!.delayedCards,
				materielCards: userPlayer.value!.materielCards,
				handCards: userPlayer.value!.handCards,
				hidden: false,
				maxCount: userPlayer.value!.buckleCards.length + userPlayer.value!.delayedCards.length + userPlayer.value!.materielCards.length + userPlayer.value!.handCards.length,
			});
			if (ids) socketGetPlayerCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId: userPlayer.value!.user.userId });
			break;
		}
		case "弃置牌": {
			const ids = await oPlayerCardsPicker.value?.open({
				buckleCards: userPlayer.value!.buckleCards,
				delayedCards: userPlayer.value!.delayedCards,
				materielCards: userPlayer.value!.materielCards,
				handCards: userPlayer.value!.handCards,
				hidden: false,
				maxCount: userPlayer.value!.buckleCards.length + userPlayer.value!.delayedCards.length + userPlayer.value!.materielCards.length + userPlayer.value!.handCards.length,
			});
			if (ids) socketTransferPlayerCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId: userPlayer.value!.user.userId, position: "bottom" });
			break;
		}
		case "设置生命上限": {
			const value = prompt("请输入生命上限", userPlayer.value!.healthLimit.toString());
			socketSetHealthLimit({ roomId: roomState.room.value!.roomId, healthLimit: Number(value) || 0 });
			break;
		}
		case "增加生命值": {
			socketSetHealth({ roomId: roomState.room.value!.roomId, health: userPlayer.value!.health + 1 });
			break;
		}
		case "减少生命值": {
			socketSetHealth({ roomId: roomState.room.value!.roomId, health: userPlayer.value!.health - 1 });
			break;
		}
		case "延时牌置于下一人": {
			const index = roomState.room.value!.players.findIndex((v) => v.user.userId === userPlayer.value!.user.userId);
			if (index !== -1) {
				const ids = await oCardsPicker.value?.open({ cards: roomState.room.value!.players[index].delayedCards, maxCount: 20, hidden: false, selectedIds: [] });
				socketTransferDelayedCardsToPlayerDelayedCards({ roomId: roomState.room.value!.roomId, userId: roomState.room.value!.players[index + 1]?.user.userId || roomState.room.value!.players[0]?.user.userId, cardIds: ids || [] });
			}
			break;
		}
		case "重设已有武将": {
			const ids = await oHerosPicker.value?.open({ heros: userPlayer.value!.heros, hidden: false, selectedIds: [] });
			if (ids) {
				socketSpeak({ roomId: roomState.room.value!.roomId, message: userStore.userInfo.username + "重设了" + ids.length + "张已有武将。" });
				socketSetHeros({ roomId: roomState.room.value!.roomId, heroIds: ids });
			}
			break;
		}
		case "切换死亡状态": {
			socketSetDead({ roomId: roomState.room.value!.roomId, dead: !userPlayer.value!.dead });
			break;
		}
	}
};
const setOtherPlayerHero = async (userId: number) => {
	const value = await Picker([
		{ label: "添加装备牌", value: "添加装备牌" },
		{ label: "添加延时牌", value: "添加延时牌" },
		{ label: "添加扣至牌", value: "添加扣至牌" },
		{ label: "给予牌", value: "给予牌" },
		{ label: "查看牌", value: "查看牌" },
		{ label: "获得牌", value: "获得牌" },
		{ label: "弃置牌", value: "弃置牌" },
	]);
	switch (value) {
		case "添加装备牌": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketAddMaterielCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId });
			break;
		}
		case "添加延时牌": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketAddDelayedCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId });
			break;
		}
		case "添加扣至牌": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketAddBuckleCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId });
			break;
		}
		case "给予牌": {
			const ids = await oPlayerCardsPicker.value?.open({
				buckleCards: userPlayer.value!.buckleCards,
				delayedCards: userPlayer.value!.delayedCards,
				materielCards: userPlayer.value!.materielCards,
				handCards: userPlayer.value!.handCards,
				hidden: false,
				maxCount: userPlayer.value!.buckleCards.length + userPlayer.value!.delayedCards.length + userPlayer.value!.materielCards.length + userPlayer.value!.handCards.length,
			});
			if (ids) socketTransferPlayerCardsToPlayerHandCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId, position: "random" });
			break;
		}
		case "获得牌": {
			const player = roomState.room.value!.players.find((v) => v.user.userId === userId);
			const ids = await oPlayerCardsPicker.value?.open({
				buckleCards: player!.buckleCards,
				delayedCards: player!.delayedCards,
				materielCards: player!.materielCards,
				handCards: player!.handCards,
				hidden: true,
				maxCount: player!.buckleCards.length + player!.delayedCards.length + player!.materielCards.length + player!.handCards.length,
			});
			if (ids) socketGetPlayerCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId });
			break;
		}
		case "弃置牌": {
			const player = roomState.room.value!.players.find((v) => v.user.userId === userId);
			const ids = await oPlayerCardsPicker.value?.open({
				buckleCards: player!.buckleCards,
				delayedCards: player!.delayedCards,
				materielCards: player!.materielCards,
				handCards: player!.handCards,
				hidden: true,
				maxCount: player!.buckleCards.length + player!.delayedCards.length + player!.materielCards.length + player!.handCards.length,
			});
			if (ids) socketTransferPlayerCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: ids, userId, position: "bottom" });
			break;
		}
		case "查看牌": {
			const player = roomState.room.value!.players.find((v) => v.user.userId === userId);
			const viewIds = await oPlayerCardsPicker.value?.open({
				userId,
				buckleCards: player!.buckleCards,
				delayedCards: player!.delayedCards,
				materielCards: player!.materielCards,
				handCards: player!.handCards,
				hidden: true,
				readOnly: true,
				maxCount: player!.buckleCards.length + player!.delayedCards.length + player!.materielCards.length + player!.handCards.length,
			});
			if (viewIds) {
				socketSpeak({ roomId: roomState.room.value!.roomId, message: "查看了" + player!.user.username + "的" + viewIds.length + "张牌。" });
				const operateIds = await oCardsPicker.value?.open({
					cards: [...player!.delayedCards.filter((v) => viewIds!.includes(v.cardId)), ...player!.materielCards.filter((v) => viewIds!.includes(v.cardId)), ...player!.handCards.filter((v) => viewIds!.includes(v.cardId))],
					maxCount: viewIds.length,
					hidden: false,
					selectedIds: viewIds,
				});
				if (operateIds) {
					const value = await Picker([
						{ label: "置于我的手牌", value: "置于我的手牌" },
						{ label: "置于弃牌堆", value: "置于弃牌堆" },
						{ label: "置于摸牌堆顶部", value: "置于摸牌堆顶部" },
						{ label: "置于摸牌堆底部", value: "置于摸牌堆底部" },
						{ label: "随机置于摸牌堆", value: "随机置于摸牌堆" },
						{ label: "置于弃牌堆顶部", value: "置于弃牌堆顶部" },
						{ label: "随机置于弃牌堆", value: "随机置于弃牌堆" },
					]);
					switch (value) {
						case "置于我的手牌":
							socketGetPlayerCards({ roomId: roomState.room.value!.roomId, userId, cardIds: operateIds });
							break;
						case "置于弃牌堆":
							socketTransferPlayerCardsToDiscardCards({ roomId: roomState.room.value!.roomId, userId, cardIds: operateIds, position: "bottom" });
							break;
						case "置于摸牌堆顶部":
							socketTransferPlayerCardsToDrawCards({ roomId: roomState.room.value!.roomId, userId, cardIds: operateIds, position: "top" });
							break;
						case "置于摸牌堆底部":
							socketTransferPlayerCardsToDrawCards({ roomId: roomState.room.value!.roomId, userId, cardIds: operateIds, position: "bottom" });
							break;
						case "随机置于摸牌堆":
							socketTransferPlayerCardsToDrawCards({ roomId: roomState.room.value!.roomId, userId, cardIds: operateIds, position: "random" });
							break;
						case "置于弃牌堆顶部":
							socketTransferPlayerCardsToDiscardCards({ roomId: roomState.room.value!.roomId, userId, cardIds: operateIds, position: "top" });
							break;
						case "随机置于弃牌堆":
							socketTransferPlayerCardsToDiscardCards({ roomId: roomState.room.value!.roomId, userId, cardIds: operateIds, position: "random" });
							break;
					}
				}
			}
			break;
		}
	}
};
const setDrawCard = async () => {
	const value = await Picker([
		{ label: "查看摸牌堆", value: "查看摸牌堆" },
		{ label: "获取摸牌堆", value: "获取摸牌堆" },
		{ label: "置于弃牌堆", value: "置于弃牌堆" },
	]);
	switch (value) {
		case "查看摸牌堆": {
			const viewIds = await oCardsPicker.value?.open({ cards: roomState.room.value!.drawCards, maxCount: 20, hidden: true });
			if (viewIds) socketViewDrawCards({ roomId: roomState.room.value!.roomId, cardIds: viewIds });
			const operateIds = await oCardsPicker.value?.open({ cards: roomState.room.value!.drawCards.filter((v) => viewIds!.includes(v.cardId)), maxCount: 20, hidden: false, selectedIds: viewIds });
			if (operateIds) {
				const value = await Picker([
					{ label: "置于我的手牌", value: "置于我的手牌" },
					{ label: "置于弃牌堆", value: "置于弃牌堆" },
					{ label: "置于摸牌堆顶部", value: "置于摸牌堆顶部" },
					{ label: "置于摸牌堆底部", value: "置于摸牌堆底部" },
					{ label: "随机置于摸牌堆", value: "随机置于摸牌堆" },
					{ label: "置于弃牌堆顶部", value: "置于弃牌堆顶部" },
					{ label: "随机置于弃牌堆", value: "随机置于弃牌堆" },
				]);
				switch (value) {
					case "置于我的手牌":
						socketGetDrawCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds });
						break;
					case "置于摸牌堆顶部":
						socketTransferDrawCardsToDrawCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "top" });
						break;
					case "置于摸牌堆底部":
						socketTransferDrawCardsToDrawCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "bottom" });
						break;
					case "随机置于摸牌堆":
						socketTransferDrawCardsToDrawCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "random" });
						break;
					case "置于弃牌堆":
						socketTransferDrawCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "bottom" });
						break;
					case "置于弃牌堆顶部":
						socketTransferDrawCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "top" });
						break;
					case "随机置于弃牌堆":
						socketTransferDrawCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "random" });
						break;
				}
			}
			break;
		}
		case "获取摸牌堆": {
			const ids = await oCardsPicker.value?.open({ cards: roomState.room.value!.drawCards, maxCount: 20, hidden: true });
			if (ids) socketGetDrawCards({ roomId: roomState.room.value!.roomId, cardIds: ids });
			break;
		}
		case "置于弃牌堆": {
			const ids = await oCardsPicker.value?.open({ cards: roomState.room.value!.drawCards, maxCount: 20, hidden: true });
			if (ids) socketTransferDrawCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: ids, position: "bottom" });
			break;
		}
	}
};
const setDiscardCard = async () => {
	const value = await Picker([
		{ label: "查看弃牌堆", value: "查看弃牌堆" },
		{ label: "获取弃牌堆", value: "获取弃牌堆" },
	]);
	switch (value) {
		case "查看弃牌堆": {
			const viewIds = await oCardsPicker.value?.open({ cards: deepClone(roomState.room.value!.discardCards).reverse(), maxCount: 10 });
			if (viewIds) socketViewDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: viewIds });
			const operateIds = await oCardsPicker.value?.open({
				cards: deepClone(roomState.room.value!.discardCards)
					.reverse()
					.filter((v) => viewIds!.includes(v.cardId)),
				maxCount: 20,
				selectedIds: viewIds,
			});
			if (operateIds) {
				const value = await Picker([
					{ label: "置于我的手牌", value: "置于我的手牌" },
					{ label: "置于摸牌堆顶部", value: "置于摸牌堆顶部" },
					{ label: "置于摸牌堆底部", value: "置于摸牌堆底部" },
					{ label: "随机置于摸牌堆", value: "随机置于摸牌堆" },
					{ label: "置于弃牌堆顶部", value: "置于弃牌堆顶部" },
					{ label: "置于弃牌堆底部", value: "置于弃牌堆底部" },
					{ label: "随机置于弃牌堆", value: "随机置于弃牌堆" },
				]);
				switch (value) {
					case "置于我的手牌":
						socketGetDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds });
						break;
					case "置于摸牌堆顶部":
						socketTransferDiscardCardsToDrawCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "top" });
						break;
					case "置于摸牌堆底部":
						socketTransferDiscardCardsToDrawCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "bottom" });
						break;
					case "随机置于摸牌堆":
						socketTransferDiscardCardsToDrawCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "random" });
						break;
					case "置于弃牌堆顶部":
						socketTransferDiscardCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "top" });
						break;
					case "置于弃牌堆底部":
						socketTransferDiscardCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "bottom" });
						break;
					case "随机置于弃牌堆":
						socketTransferDiscardCardsToDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: operateIds, position: "random" });
						break;
				}
			}
			break;
		}
		case "获取弃牌堆": {
			const ids = await oCardsPicker.value?.open({ cards: deepClone(roomState.room.value!.discardCards).reverse(), maxCount: 20 });
			if (ids) socketGetDiscardCards({ roomId: roomState.room.value!.roomId, cardIds: ids });
			break;
		}
	}
};
const setUserPlayerCards = async () => {
	const value = await Picker([
		{ label: "弃置", value: "弃置" },
		{ label: "置于摸牌堆顶部", value: "置于摸牌堆顶部" },
		{ label: "置于摸牌堆底部", value: "置于摸牌堆底部" },
		{ label: "随机置于摸牌堆", value: "随机置于摸牌堆" },
		{ label: "置于弃牌堆顶部", value: "置于弃牌堆顶部" },
		{ label: "随机置于弃牌堆", value: "随机置于弃牌堆" },
	]);
	switch (value) {
		case "置于摸牌堆顶部": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketTransferPlayerCardsToDrawCards({ roomId: roomState.room.value!.roomId, userId: userStore.userInfo.userId, cardIds: ids, position: "top" });
			break;
		}
		case "置于摸牌堆底部": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketTransferPlayerCardsToDrawCards({ roomId: roomState.room.value!.roomId, userId: userStore.userInfo.userId, cardIds: ids, position: "bottom" });
			break;
		}
		case "随机置于摸牌堆": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketTransferPlayerCardsToDrawCards({ roomId: roomState.room.value!.roomId, userId: userStore.userInfo.userId, cardIds: ids, position: "random" });
			break;
		}
		case "置于弃牌堆顶部": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketTransferPlayerCardsToDiscardCards({ roomId: roomState.room.value!.roomId, userId: userStore.userInfo.userId, cardIds: ids, position: "top" });
			break;
		}
		case "弃置": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketTransferPlayerCardsToDiscardCards({ roomId: roomState.room.value!.roomId, userId: userStore.userInfo.userId, cardIds: ids, position: "bottom" });
			break;
		}
		case "随机置于弃牌堆": {
			const ids = await oCardsPicker.value?.open({ cards: userPlayer.value!.handCards, maxCount: userPlayer.value!.handCards.length });
			if (ids) socketTransferPlayerCardsToDiscardCards({ roomId: roomState.room.value!.roomId, userId: userStore.userInfo.userId, cardIds: ids, position: "random" });
			break;
		}
	}
};
const heroMousedown = (hero: Hero) => {
	let timer = setTimeout(() => {
		oHeroDetail.value?.open({ hero });
	}, 200);
	document.body.addEventListener("mouseup", fn);
	function fn() {
		clearTimeout(timer);
		document.body.removeEventListener("mouseup", fn);
	}
};
const cardMousedown = (card: Card) => {
	let timer = setTimeout(() => {
		oCardDetail.value?.open({ card });
	}, 200);
	document.body.addEventListener("mouseup", fn);
	function fn() {
		clearTimeout(timer);
		document.body.removeEventListener("mouseup", fn);
	}
};
const heroTouchStart = (hero: Hero) => {
	let timer = setTimeout(() => {
		oHeroDetail.value?.open({ hero });
	}, 200);
	document.body.addEventListener("touchend", fn);
	function fn() {
		clearTimeout(timer);
		document.body.removeEventListener("touchend", fn);
	}
};
const cardTouchStart = (card: Card) => {
	let timer = setTimeout(() => {
		oCardDetail.value?.open({ card });
	}, 200);
	document.body.addEventListener("touchend", fn);
	function fn() {
		clearTimeout(timer);
		document.body.removeEventListener("touchend", fn);
	}
};
const speakSkill = (skill: Skill) => {
	socketSpeak({ roomId: roomState.room.value!.roomId, message: skill.content, voice: skill.voice });
};
</script>

<template>
	<div v-if="roomState.room.value" class="room">
		<div class="playground">
			<div class="players">
				<div v-for="v in otherPlayersV2" :key="v.user.userId" :class="{ player: true, card: true, 'hero-card': true, tied: v.tied, dead: v.dead }">
					<span class="number">{{ (roomState.room.value.players.findIndex((v2) => v2.user.userId === v.user.userId) || 0) + 1 }}</span>
					<ul class="delay-cards">
						<li v-for="v2 in v.delayedCards" :key="v2.cardId">{{ v2.name[0] }}</li>
					</ul>
					<p v-if="roomState.speaking.some((v2) => v2.userId === v.user.userId)" class="message">{{ roomState.speaking.find((v2) => v2.userId === v.user.userId)!.message }}</p>
					<div
						v-if="v.heros[0]"
						:class="{
							title: true,
							wei: !v.hiddenHeroIds.length && v.heros[0].factions.includes('魏'),
							shu: !v.hiddenHeroIds.length && v.heros[0].factions.includes('蜀'),
							wu: !v.hiddenHeroIds.length && v.heros[0].factions.includes('吴'),
							qun: !v.hiddenHeroIds.length && v.heros[0].factions.includes('群'),
							ye: !v.hiddenHeroIds.length && v.heros[0].factions.includes('野'),
							shen: !v.hiddenHeroIds.length && v.heros[0].factions.includes('神'),
						}"
					>
						<template v-if="!v.hiddenHeroIds.length">
							<i v-for="v2 in v.heros[0].factions" :key="v2">{{ v2 }}</i>
						</template>
						<b v-if="!v.hiddenHeroIds.length">{{ v.heros.map((v) => v.name).join("&") }}</b>
						<p class="blood-count">
							<svg class="icon"><use href="#droplet" /></svg>
							<span>{{ v.health }}/{{ v.healthLimit }}</span>
						</p>
						<p class="hand-card-count">
							<svg class="icon"><use href="#tablet" /></svg>
							<span>{{ v.handCards.length }}</span>
						</p>
					</div>
					<div class="content" @click="setOtherPlayerHero(v.user.userId)">
						<div :class="{ covers: true, flipped: v.flipped }">
							<picture
								v-for="(v2, i2) in v.heros"
								:key="v2.heroId"
								:class="{ hidden: v.hiddenHeroIds.includes(v2.heroId) }"
								@mousedown="!v.hiddenHeroIds.includes(v2.heroId) && heroMousedown(v2)"
								@touchstart="!v.hiddenHeroIds.includes(v2.heroId) && heroTouchStart(v2)"
							>
								<img :src="STATIC_URL + v2.skins.find(v3=>v3.skinId == v!.currentHerosSkinId[i2])?.src || ''" alt="" />
							</picture>
						</div>
						<div v-if="v.buckleCards.length" class="marks">
							<mark>扣至：{{ v.buckleCards.length }}</mark>
						</div>
						<div class="marks">
							<mark v-for="(v2, i2) in v.marks" :key="i2">{{ v2.name }}</mark>
						</div>
						<ul class="materiels">
							<li v-for="v2 in v.materielCards" :key="v2.cardId">
								<span>{{ v2.name }}</span>
								<b :class="{ red: v2.suit == 'heart' || v2.suit == 'diamond' }">{{ suit_icon_dict[v2.suit] }} {{ v2.rank }}</b>
							</li>
						</ul>
					</div>
				</div>
			</div>
			<div class="middle">
				<TransitionGroup name="list-top" tag="div" class="cards" @click="setDrawCard()">
					<div v-for="(v, i) in deepClone(roomState.room.value.drawCards).reverse()" :key="v.cardId" class="card hand-card" :style="{ left: i * 1 + 'rem' }"></div>
				</TransitionGroup>
				<button class="primary menu" @click="openMenu()">菜单</button>
				<TransitionGroup name="list-top" tag="div" class="discard cards" @click="setDiscardCard()">
					<div v-for="(v, i) in roomState.room.value.discardCards.slice(-4)" :key="v.cardId" class="card hand-card" :style="{ right: i * 50 + 'rem' }">
						<div :class="{ suit: true, red: v.suit == 'heart' || v.suit == 'diamond' }">
							<span>{{ suit_icon_dict[v.suit] }}</span>
							<span>{{ v.rank }}</span>
						</div>
						<img :src="STATIC_URL + v.src" alt="" />
					</div>
				</TransitionGroup>
			</div>
			<div v-if="userPlayer" class="user-player">
				<TransitionGroup name="list-top" tag="div" class="user-player-hand-cards" @click="setUserPlayerCards()">
					<div v-for="v in userPlayer.handCards" :key="v.cardId" class="card hand-card" @mousedown="cardMousedown(v)" @touchstart="cardTouchStart(v)">
						<div :class="{ suit: true, red: v.suit == 'heart' || v.suit == 'diamond' }">
							<span>{{ suit_icon_dict[v.suit] }}</span>
							<span>{{ v.rank }}</span>
						</div>
						<img :src="STATIC_URL + v.src" alt="" />
					</div>
				</TransitionGroup>
				<div class="skills">
					<button v-for="v in userPlayer.skills" :key="v.skillId" @click="speakSkill(v)">{{ v.name }}</button>
				</div>
				<div :class="{ card: true, 'hero-card': true, tied: userPlayer.tied, dead: userPlayer.dead }">
					<span class="number">{{ (roomState.room.value.players.findIndex((v) => v.user.userId === userStore.userInfo.userId) || 0) + 1 }}</span>
					<ul class="delay-cards">
						<li v-for="v in userPlayer.delayedCards" :key="v.cardId">{{ v.name[0] }}</li>
					</ul>
					<p v-if="roomState.speaking.some(v=>v.userId === userPlayer!.user.userId)" class="message">{{ roomState.speaking.find((v) => v.userId === userPlayer!.user.userId)!.message }}</p>
					<div
						v-if="userPlayer.heros[0]"
						:class="{
							title: true,
							wei: userPlayer.heros[0].factions[0] == '魏',
							shu: userPlayer.heros[0].factions[0] == '蜀',
							wu: userPlayer.heros[0].factions[0] == '吴',
							qun: userPlayer.heros[0].factions[0] == '群',
							ye: userPlayer.heros[0].factions[0] == '野',
							shen: userPlayer.heros[0].factions[0] == '神',
						}"
					>
						<i v-for="v in userPlayer.heros[0].factions" :key="v">{{ v }}</i>
						<b>{{ userPlayer.heros.map((v) => v.name).join("&") }}</b>
						<p class="blood-count" @click="setUserPlayerHero()">
							<svg class="icon"><use href="#droplet" /></svg>
							<span>{{ userPlayer.health }}/{{ userPlayer.healthLimit }}</span>
						</p>
						<p class="hand-card-count">
							<svg class="icon"><use href="#tablet" /></svg>
							<span>{{ userPlayer.handCards.length }}</span>
						</p>
					</div>
					<div class="content" @click="setUserPlayerHero()">
						<div :class="{ covers: true, flipped: userPlayer.flipped }">
							<picture v-for="(v, i) in userPlayer.heros" :key="v.heroId" :class="{ hidden: userPlayer.hiddenHeroIds.includes(v.heroId) }" @mousedown="heroMousedown(v)" @touchstart="heroTouchStart(v)">
								<img :src="STATIC_URL + v.skins.find(v=>v.skinId == userPlayer!.currentHerosSkinId[i])?.src || ''" alt="" />
							</picture>
						</div>
						<div v-if="userPlayer.buckleCards.length" class="marks">
							<mark>扣至：{{ userPlayer.buckleCards.length }}</mark>
						</div>
						<div class="marks">
							<mark v-for="(v, i) in userPlayer.marks" :key="i">{{ v.name }}</mark>
						</div>
						<ul class="materiels">
							<li v-for="v in userPlayer.materielCards" :key="v.cardId">
								<span>{{ v.name }}</span>
								<b :class="{ red: v.suit == 'heart' || v.suit == 'diamond' }">{{ suit_icon_dict[v.suit] }} {{ v.rank }}</b>
							</li>
						</ul>
					</div>
				</div>
			</div>
		</div>
		<div :class="{ log: true, expanded: logExpanded }">
			<button @click="logExpanded = !logExpanded">展</button>
			<ul ref="oLog">
				<li v-for="(v, i) in roomState.room.value.logs.slice(-100)" :key="i">{{ v.username }}：{{ v.log }}</li>
			</ul>
		</div>
		<HerosPicker ref="oHerosPicker" />
		<CardsPicker ref="oCardsPicker" />
		<PlayerCardsPicker ref="oPlayerCardsPicker" />
		<HeroDetail ref="oHeroDetail" />
		<CardDetail ref="oCardDetail" />
	</div>
</template>

<style scoped lang="scss">
.room {
	width: 100%;
	height: 100%;
	display: flex;
	background-color: #7c633d;
	overflow: hidden;
	.playground {
		box-sizing: border-box;
		position: relative;
		padding: 20rem 30rem 10rem;
		width: 100%;
		height: 100%;
		display: flex;
		flex-direction: column;
		overflow: hidden;
		.players {
			flex-shrink: 0;
			display: flex;
			justify-content: space-between;
			.player {
				&:nth-child(1),
				&:nth-child(7) {
					margin-top: 6rem;
				}
				&:nth-child(2),
				&:nth-child(6) {
					margin-top: 4rem;
				}
				&:nth-child(3),
				&:nth-child(5) {
					margin-top: 2rem;
				}
			}
			.content {
				.hidden::after {
					background-color: #000;
				}
			}
		}
		.middle {
			flex: 1;
			display: flex;
			justify-content: space-between;
			align-items: center;
			.cards {
				width: 50.4rem;
				height: 70.4rem;
				position: relative;
				display: flex;
				border-radius: 4rem;
				background-color: #ccc;
			}
			.menu {
				width: 50rem;
				height: 50rem;
				font-size: 14rem;
			}
			.hand-card {
				position: absolute;
				width: 50.4rem;
				height: 70.4rem;
			}
		}
		.user-player {
			flex-shrink: 0;
			width: 100%;
			display: flex;
			align-items: flex-end;
			column-gap: 4rem;
			.user-player-hand-cards {
				flex: 1;
				column-gap: 2rem;
				display: flex;
				overflow-y: hidden;
				overflow-x: auto;
			}
			.skills {
				display: flex;
				flex-direction: column;
				max-height: 106rem;
				overflow: auto;
				gap: 6rem;
				&::-webkit-scrollbar {
					display: none;
				}
				button {
					flex-shrink: 0;
					width: 42rem;
					height: 24rem;
					font-size: 12rem;
					font-weight: bold;
					color: #d6d7a5;
					background-color: #353f25;
					border-radius: 2rem;
				}
			}
		}
	}
	.log {
		position: absolute;
		top: 0;
		right: 0;
		width: 120rem;
		height: 40rem;
		display: flex;
		flex-direction: column;
		background-color: rgba(0, 0, 0, 0.5);
		box-shadow: 0 0 3rem 1rem #333;
		transition: height 0.2s;
		z-index: 9;
		&.expanded {
			height: 100%;
		}
		button {
			position: absolute;
			top: 50%;
			transform: translateY(-50%);
			left: -20rem;
			width: 20rem;
			height: 20rem;
			color: #fff;
			font-size: 12rem;
			background-color: rgba(0, 0, 0, 0.5);
			box-shadow: 0 0 3rem 1rem #333;
		}
		ul {
			flex: 1;
			padding: 6rem;
			display: flex;
			flex-direction: column;
			overflow: auto;
			row-gap: 6rem;
			transition: padding 0.2s;
			li {
				color: #fff;
				font-size: 10rem;
			}
		}
	}
}
.list-top-move, /* 对移动中的元素应用的过渡 */
.list-top-enter-active,
.list-top-leave-active {
	transition: opacity 0.2s, transform 0.2s;
}

.list-top-enter-from,
.list-top-leave-to {
	opacity: 0;
	transform: translateY(-100%);
}

/* 确保将离开的元素从布局流中删除
  以便能够正确地计算移动的动画。 */
.list-top-leave-active {
	position: absolute;
}
</style>
